package com.jimmy.medical.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jimmy.medical.base.impl.JpaSpecificationServiceImpl;
import com.jimmy.medical.common.StringUtils;
import com.jimmy.medical.entity.*;
import com.jimmy.medical.entity.Order;
import com.jimmy.medical.enums.*;
import com.jimmy.medical.model.OrderReport;
import com.jimmy.medical.model.SignInfo;
import com.jimmy.medical.model.UserTask;
import com.jimmy.medical.repository.*;
import com.jimmy.medical.service.IDictService;
import com.jimmy.medical.service.IFlowOrderService;
import com.jimmy.medical.util.CommonUtils;
import com.jimmy.medical.util.MobileUtils;
import com.jimmy.medical.model.FeeInfo;
import org.apache.commons.collections.IteratorUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.text.DecimalFormat;
import java.util.*;

@Service
@Qualifier("flowOrderService")
public class FlowOrderServiceImpl extends JpaSpecificationServiceImpl<FlowOrderRepository, FlowOrderRepository, FlowOrder, Long>
        implements IFlowOrderService {

    @Autowired
    protected FlowOrderRepository repository;
    @Autowired
    private FlowOrderLogRepository flowOrderLogRepository;
    @Autowired
    protected UserRepository userRepository;
    @Autowired
    private FlowOrderTypeRepository flowOrderTypeRepository;
    @Autowired
    private PhoneCallRepository phoneCallRepository;
    @Autowired
    private MessageRepository messageRepository;
    @Autowired
    private MobileUtils mobileUtils;
    @Autowired
    protected UploadFileRepository uploadFileRepository;
    @Autowired
    protected OrderRepository orderRepository;
    @Autowired
    private OrderTypeRepository orderTypeRepository;
    @Autowired
    protected OrderHistoryRepository orderHistoryRepository;
    @Autowired
    protected MeasuresRepository measuresRepository;
    @Autowired
    private HospitalRepository hospitalRepository;
    @Autowired
    private DepartmentRepository departmentRepository;
    @Autowired
    private DoctorRepository doctorRepository;
    @Autowired
    private MedicineRepository medicineRepository;
    @Autowired
    private DiseaseDicRepository diseaseDicRepository;
    @Autowired
    protected OrderExecutionRecordRepository orderExecutionRecordRepository;
    @Autowired
    protected OrderExceptionDataRepository orderExceptionDataRepository;
    @Autowired
    protected OrderDiagnoseRepository orderDiagnoseRepository;
    @Autowired
    protected OrderMedicineRepository orderMedicineRepository;
    @Autowired
    private IDictService dictService;

    private DecimalFormat df = new DecimalFormat("0.00");

    public List<FlowOrder> findByUser(User user) {
        return repository.findByUser(user);
    }

    public FlowOrder getDetail(Long id) {
        FlowOrder flowOrder = repository.findOne(id);
        flowOrder.setCountDown(getCountDown(flowOrder));
        flowOrder.setLogList(flowOrderLogRepository.findByFlowOrderOrderByTimeFinishDesc(flowOrder));
        if(flowOrder.getOrder() != null) {
            flowOrder.setNeedPicList(orderRepository.findNeedFile(flowOrder.getOrder().getId(), 1));
            flowOrder.setNeedDocList(orderRepository.findNeedFile(flowOrder.getOrder().getId(), 2));
        }

        return flowOrder;
    }

    @Override
    public Page<FlowOrder> findAll(Pageable pageable, final Long userId, final Long flowOrderType, final Long orderType, final Short isFinish, final Integer currentStep, final Short isAssign, final String keyword) {
        return this.findAll(new Specification<FlowOrder>() {
            @Override
            public Predicate toPredicate(Root<FlowOrder> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Join<FlowOrder, Order> orderJoin = root.join("order", JoinType.LEFT);
                Join<FlowOrder, OrderType> orderTypeJoin = root.join("orderType", JoinType.LEFT);
                Join<Order, Member> memberJoin = orderJoin.join("member", JoinType.LEFT);
                Join<FlowOrder, User> userJoin = root.join("user", JoinType.LEFT);
                Join<FlowOrder, FlowOrderType> flowOrderTypeJoin = root.join("flowOrderType", JoinType.LEFT);

                Path<Short> isFinishPath = root.get("isFinish");
                Path<Short> isAssignPath = root.get("isAssign");
                Path<Integer> currentStepPath = root.get("currentStep");
                Path<Long> userIdPath = userJoin.get("id");
                Path<String> memberNamePath = memberJoin.get("realname");
                Path<Long> orderIdPath = orderJoin.get("id");
                Path<Long> orderTypePath = orderTypeJoin.get("id");
                Path<Long> flowOrderTypeIdPath = flowOrderTypeJoin.get("id");

                ArrayList<Predicate> list = new ArrayList<Predicate>();
                if(currentStep != null) {
                    list.add(criteriaBuilder.equal(currentStepPath, currentStep));
                } else {
                    list.add(criteriaBuilder.notEqual(currentStepPath, OrderStatusEnum.CANCELED.getKey()));
                }

                if(isFinish != null) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(isFinishPath, isFinish)));
                }

                if(isAssign != null) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(isAssignPath, isAssign)));
                }

                if (userId != null) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(userIdPath, userId)));
                }

                if (flowOrderType != null && flowOrderType > 0) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(flowOrderTypeIdPath, flowOrderType)));
                }

                if(orderType != null && orderType > 0) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(orderTypePath, orderType)));
                }

                if (StringUtils.isNotBlank(keyword)) {
                    if (!StringUtils.isNumericSpace(keyword)) {
                        list.add(criteriaBuilder.or(
                                criteriaBuilder.like(memberNamePath, keyword + "%")
                        ));
                    } else {
                        list.add(criteriaBuilder.or(
                                criteriaBuilder.equal(orderIdPath, keyword),
                                criteriaBuilder.like(memberNamePath, keyword + "%")
                        ));
                    }
                }

                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        }, pageable);
    }

    @Override
    public List<FlowOrderType> flowOrderTypeList() {
        Sort sort = new Sort(Sort.Direction.ASC, "typeOrder");
        return IteratorUtils.toList(flowOrderTypeRepository.findAll(sort).iterator());
    }

    @Override
    public void saveDialInfo(PhoneCall call) {
        FlowOrder flowOrder = repository.findOne(call.getOrderId());
        if (call.getIsNeedDailToMember() != null && call.getIsNeedDailToMember() == 1) {
            User optUser = userRepository.findOne(call.getUserId());
            call.setCallTime(new Date());
            call.setFlowOrder(flowOrder);
            call.setUser(optUser);
            phoneCallRepository.save(call);
        }
    }

    @Override
    public void saveMessageInfo(Message message) {
        FlowOrder flowOrder = repository.findOne(message.getOrderId());

        mobileUtils.sendMessage(message.getMobile(), message.getContent(), CommonUtils.getNowTimeShortString());

        User optUser = userRepository.findOne(message.getUserId());
        message.setCreateTime(CommonUtils.getNowTimeShortString());
        message.setCreateUser(optUser.getRealname());
        message.setFlowOrderId(flowOrder.getId());
        message.setMember(flowOrder.getOrder().getMember());
        message.setOrderId(flowOrder.getOrder().getId());
        message.setStatus("Success");
        message.setSuccessCounts(1);
        messageRepository.save(message);
    }

    public Long saveSignInfo(SignInfo info, int currentStep) {
        return saveSignInfo(info, currentStep, true);
    }

    @Override
    public Long saveSignInfo(SignInfo info, int currentStep, boolean processFlow) {
        FlowOrder flowOrder;
        if(processFlow) {
            flowOrder = process(info.getOrderId(), info.getUserId(), "挂号登记", currentStep);
        } else {
            flowOrder = repository.findOne(info.getOrderId());
        }

        Order originOrder = flowOrder.getOrder();
        if (originOrder != null) {
            //设置更新字段
            originOrder.setOrderDate(info.getDate());
            originOrder.setOrderTime(info.getTime());

            if (info.getHospital() != null && info.getHospital() > 0) {
                Hospital hospital = hospitalRepository.findOne(info.getHospital());
                originOrder.setHospital(hospital);
            }
            if (info.getDepartment() != null && info.getDepartment() > 0) {
                HospitalDepartment department = departmentRepository.findOne(info.getDepartment());
                originOrder.setDepartment(department);
            }
            if (info.getDoctor() != null && info.getDoctor() > 0) {
                Doctor doctor = doctorRepository.findOne(info.getDoctor());
                originOrder.setDoctor(doctor);
            }
            if (StringUtils.isNotBlank(info.getAdvanceVoucher())) {
                String[] idArray = info.getAdvanceVoucher().split(",");
                for (String id : idArray) {
                    UploadFile voucher = uploadFileRepository.findOne(Long.valueOf(id));
                    if (voucher != null) {
                        voucher.setRelatedKey(originOrder.getId() + "");
                        voucher.setUseType(PictureUseTypeEnum.ADVANCE_FEE.getKey());
                        uploadFileRepository.save(voucher);
                    }
                }
            }
            if (StringUtils.isNotBlank(info.getReimburseVoucher())) {
                String[] idArray = info.getReimburseVoucher().split(",");
                for (String id : idArray) {
                    UploadFile voucher = uploadFileRepository.findOne(Long.valueOf(id));
                    if (voucher != null) {
                        voucher.setRelatedKey(originOrder.getId() + "");
                        voucher.setUseType(PictureUseTypeEnum.REIMBURSE_FEE.getKey());
                        uploadFileRepository.save(voucher);
                    }
                }
            }
            originOrder.setSignStatus(SignStatusEnum.YES.getKey());
            originOrder.setStatus(OrderStatusEnum.SIGNED.getKey() + "");    //状态设置为已挂号
            //费用相关字段
            originOrder.setPayAmount(info.getAdvanceFee() != null ? info.getAdvanceFee().intValue() : 0);
            originOrder.setCostAmount(info.getReimburseFee() != null ? info.getReimburseFee().intValue() : 0);
            //设置更新时间
            User optUser = userRepository.findOne(info.getUserId());
            originOrder.setUpdateTime(CommonUtils.getNowTimeShortString());
            originOrder.setUpdateUser(optUser.getRealname());
            originOrder.setIsSignRead(YnEnum.NO.getKey() + "");
            originOrder.setSignUser(optUser.getRealname());

            orderRepository.save(originOrder);
            String message = "订单挂号登记，状态改为" + OrderStatusEnum.SIGNED.getText() + "("
                    + OrderStatusEnum.SIGNED.getKey() + ")";
            OrderHistory history = new OrderHistory("挂号登记", message, originOrder, optUser.getRealname(), CommonUtils.getNowTimeShortString());
            orderHistoryRepository.save(history);
        }

        return getCountDown(flowOrder);
    }

    @Override
    public FeeInfo getMemberFeeInfo(Long flowOrderId) {
        FlowOrder flowOrder = repository.findOne(flowOrderId);
        FeeInfo fee = new FeeInfo();
        fee.setCurrent(flowOrder.getOrder().getRechargeRecord());

        if (flowOrder.getOrder() != null) {
            Order order = flowOrder.getOrder();
            fee.setFee(order.getPayAmount().doubleValue());
            List<UploadFile> voucherList = uploadFileRepository.findAllByRelatedKeyAndUseType(order.getId().toString(), PictureUseTypeEnum.ADVANCE_FEE.getKey());
            fee.setVoucherList(voucherList);
            if (order.getMember() != null) {
                Member member = order.getMember();
                List<RechargeRecord> singleServiceList = repository.findMemberRechargeRecord(member, "2", order.getCreateTime(), "1");
                List<RechargeRecord> contractList = repository.findMemberRechargeRecord(member, "1", order.getCreateTime(), "1");
                fee.setSingleServiceList(singleServiceList);
                fee.setContractList(contractList);
            }
        }

        return fee;
    }

    /**
     * 当前订单费用是否已处理
     *
     * @param flowOrderId
     * @return
     */
    public boolean isFeeProcess(Long flowOrderId) {
        FlowOrder flowOrder = repository.findOne(flowOrderId);
        if (flowOrder.getOrder() != null && flowOrder.getOrder().getRechargeRecord() != null) {
            RechargeRecord rechargeRecord = flowOrder.getOrder().getRechargeRecord();
            if (StringUtils.isNotBlank(rechargeRecord.getStatus()) && rechargeRecord.getStatus().equals("1")) {
                return false;
            }
        }

        return true;
    }

    @Override
    public Long saveFeeProcess(Long flowOrderId, Long userId, int currentStep) {
        FlowOrder flowOrder = process(flowOrderId, userId, "费用处理", currentStep);

        User user = userRepository.findOne(userId);
        Order order = flowOrder.getOrder();
        order.setStatus(OrderStatusEnum.SETTLE_ACCOUNTS.getKey() + "");
        order.setUpdateTime(CommonUtils.getNowTimeShortString());
        order.setUpdateUser(user.getRealname());
        order.setFeeProcessUser(user.getRealname());
        orderRepository.save(order);

        OrderHistory history = new OrderHistory("费用处理", "订单状态修改为已结算(40)", order, user.getRealname(), CommonUtils.getNowTimeShortString());
        orderHistoryRepository.save(history);
        return getCountDown(flowOrder);
    }

    @Override
    public Long saveExecutionRecord(OrderExecutionRecord record, String exceptionData, String diagnoseData, String medicineData, int currentStep, boolean processFlow) {
        List<OrderExceptionData> exceptionDataList = new ArrayList<OrderExceptionData>();
        if (StringUtils.isNotBlank(exceptionData)) {
            JSONArray dataArray = JSON.parseArray(exceptionData);
            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject data = dataArray.getJSONObject(i);
                exceptionDataList.add(JSON.parseObject(data.toJSONString(), OrderExceptionData.class));
            }
        }

        List<OrderDiagnose> diagnoseList = new ArrayList<OrderDiagnose>();
        if (StringUtils.isNotBlank(diagnoseData)) {
            JSONArray dataArray = JSON.parseArray(diagnoseData);
            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject data = dataArray.getJSONObject(i);
                diagnoseList.add(JSON.parseObject(data.toJSONString(), OrderDiagnose.class));
            }
        }

        List<OrderMedicine> medicineList = new ArrayList<OrderMedicine>();
        if (StringUtils.isNotBlank(medicineData)) {
            JSONArray dataArray = JSON.parseArray(medicineData);
            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject data = dataArray.getJSONObject(i);
                medicineList.add(JSON.parseObject(data.toJSONString(), OrderMedicine.class));
            }
        }

        return saveExecutionRecord(record, exceptionDataList, diagnoseList, medicineList, currentStep, processFlow);
    }

    @Override
    public Long saveExecutionRecord(OrderExecutionRecord record, List<OrderExceptionData> exceptionDataList, List<OrderDiagnose> diagnoseList, List<OrderMedicine> medicineList, int currentStep, boolean processFlow) {
        FlowOrder flowOrder;
        if(processFlow) {
            flowOrder = process(record.getFlowOrderId(), record.getUserID(), "添加记录", currentStep);
        } else {
            flowOrder = repository.findOne(record.getFlowOrderId());
        }
        User user = userRepository.findOne(record.getUserID());
        Order order = flowOrder.getOrder();

        if (record.getId() == null) {
            record.setCreateTime(CommonUtils.getNowTimeShortString());
            record.setCreateUser(user.getRealname());
            record.setIsRead(YnEnum.NO.getKey());
            record.setOrder(order);
            orderExecutionRecordRepository.save(record);
        } else {
            OrderExecutionRecord dbRecord = orderExecutionRecordRepository.findOne(record.getId());
            dbRecord.setServiceItem(record.getServiceItem());
            dbRecord.setCheckInfo(record.getCheckInfo());
            dbRecord.setExceptionResult(record.getExceptionResult());
            dbRecord.setDiagnoseResult(record.getDiagnoseResult());
            dbRecord.setPaper(record.getPaper());
            dbRecord.setRecheckAdvice(record.getRecheckAdvice());
            dbRecord.setNote(record.getNote());
            dbRecord.setCustomerBackCollection(record.getCustomerBackCollection());
            dbRecord.setInfo(record.getInfo());
            dbRecord.setHasCheckRecord(record.getHasCheckRecord());
            dbRecord.setCheckReport(record.getCheckReport());
            dbRecord.setUpdateTime(CommonUtils.getNowTimeShortString());
            dbRecord.setUpdateUser(user.getRealname());
            dbRecord.setIsRead(YnEnum.NO.getKey());
            orderExecutionRecordRepository.save(dbRecord);
        }


        order.setDiagonseUser(user.getRealname());
        order.setExecuteUser(user.getRealname());
        order.setIsReportRead(YnEnum.NO.getKey() + "");
        order.setStatus(OrderStatusEnum.EXECUTED.getKey() + "");
        orderRepository.save(order);

        if (exceptionDataList != null) {
            orderExceptionDataRepository.delete(orderExceptionDataRepository.findByOrder(order));
            for (OrderExceptionData data : exceptionDataList) {
                data.setCreateTime(CommonUtils.getNowTimeShortString());
                data.setCreateUser(user.getRealname());
                data.setOrder(order);
                orderExceptionDataRepository.save(data);
            }
        }

        if (diagnoseList != null) {
            orderDiagnoseRepository.delete(orderDiagnoseRepository.findByOrder(order));
            for (OrderDiagnose diagnose : diagnoseList) {
                diagnose.setCreateTime(CommonUtils.getNowTimeShortString());
                diagnose.setCreateUser(user.getRealname());
                diagnose.setOrder(order);
                orderDiagnoseRepository.save(diagnose);
            }
        }

        if (medicineList != null) {
            orderMedicineRepository.delete(orderMedicineRepository.findByOrder(order));
            for (OrderMedicine medicine : medicineList) {
                medicine.setCreateTime(CommonUtils.getNowTimeShortString());
                medicine.setCreateUser(user.getRealname());
                medicine.setOrder(order);
                orderMedicineRepository.save(medicine);
            }
        }

        OrderHistory history = new OrderHistory("添加记录", "订单状态修改为已执行(50)", order, user.getRealname(), CommonUtils.getNowTimeShortString());
        orderHistoryRepository.save(history);

        return getCountDown(flowOrder);
    }

    @Override
    public List<PhoneCall> getPhoneCallList(Long flowOrderId, String type) {
        return phoneCallRepository.findCallsByFlowOrderId(flowOrderId, type);
    }

    @Override
    public List<Message> getMessageList(Long flowOrderId) {
        return messageRepository.findByFlowOrderId(flowOrderId);
    }

    public FlowOrderType getNextFlowOrderType(FlowOrder flowOrder) {
        return getNextFlowOrderType(flowOrder.getOrderType(), flowOrder.getFlowOrderType());
    }

    /**
     * 查找下一个工单类型，生成新的工单
     *
     * @param orderType            订单类型
     * @param currentFlowOrderType 当前工单类型
     * @return
     */
    public FlowOrderType getNextFlowOrderType(OrderType orderType, FlowOrderType currentFlowOrderType) {
        Set<FlowOrderType> typeSet = orderType.getFlowOrderTypes();

        List<FlowOrderType> typeList = Arrays.asList(typeSet.toArray(new FlowOrderType[]{}));
        Collections.sort(typeList);

        FlowOrderType nextType = null;
        int index = typeList.indexOf(currentFlowOrderType);
        if(index >= 0 && index < typeList.size()-1) {
            nextType = typeList.get(index+1);
        }

        return nextType;
    }

    @Override
    public FlowOrder getNextFlowOrder(FlowOrder flowOrder) {
        FlowOrderType nextType = getNextFlowOrderType(flowOrder);
        if (nextType != null) {
            FlowOrder next = new FlowOrder();
            next.setCreateTime(new Date());
            next.setUpdateTime(new Date());
            next.setCurrentStep(0);
            next.setIsFinish((short)0);
            next.setIsAssign((short)0);
            next.setIsEvaluate((short)0);
            next.setIsOverTime((short)0);
            next.setIsSettle((short)0);
            next.setFlowOrderType(nextType);
            next.setOrder(flowOrder.getOrder());
            next.setOrderType(flowOrder.getOrderType());

            flowOrder.setScore((short)0);
            flowOrder.setMoney(0D);

            if(nextType.getDefaultScore() != null) {
                flowOrder.setScore(nextType.getDefaultScore().shortValue());
                if(nextType.getPrice() != null) {
                    String d = df.format(nextType.getPrice()*nextType.getDefaultScore()*1.0D/10);
                    flowOrder.setMoney(new Double(d));
                }
            }

            repository.save(next);
            return next;
        }

        return null;
    }

    public Long getCountDown(FlowOrder flowOrder) {
        FlowOrderType flowOrderType = flowOrder.getFlowOrderType();
        FlowOrderServiceItem currentItem = null;
        //初始步骤按第一步来计算
        boolean currentStetpIsZero = false;
        if(flowOrder.getCurrentStep() == 0) {
            flowOrder.setCurrentStep(1);
            currentStetpIsZero = true;
        }
        for (FlowOrderServiceItem item : flowOrderType.getFlowOrderTypes()) {
            if (item.getItemOrder() == flowOrder.getCurrentStep()) {
                currentItem = item;
                break;
            }
        }

        if(currentStetpIsZero) {
            flowOrder.setCurrentStep(0);
        }

        if (currentItem == null) {
            return 0l;
        }

        if (currentItem.getCountDownType().equals("1")) {
            return 0l;
        } else {
            Calendar cal = Calendar.getInstance();
            cal.setTime(flowOrder.getUpdateTime() != null ? flowOrder.getUpdateTime() : flowOrder.getCreateTime());
            cal.add(Calendar.MINUTE, currentItem.getCountDown());

            return cal.getTimeInMillis();
        }
    }

    @Override
    public Long getCountDown(Long flowOrderId) {
        FlowOrder flowOrder = repository.findOne(flowOrderId);
        return getCountDown(flowOrder);
    }

    /**
     * 计算工单订单倒计时
     * @param flowOrderId
     * @return
     */
    public Long getCountDownInternal(Long flowOrderId) {
        FlowOrder flowOrder = repository.findOne(flowOrderId);
        return getCountDownInternal(flowOrder);
    }

    public Long getCountDownInternal(FlowOrder flowOrder) {
        Long limit = getCountDown(flowOrder);
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        return cal.getTimeInMillis() - limit;
    }

    public String getTimeLimit(FlowOrder flowOrder) {
        return CommonUtils.formatDate("yyyy-MM-dd HH:mm:ss", new Date(getCountDown(flowOrder)));
    }

    public FlowOrder process(Long flowOrderId, Long userId, String logContent, Integer currentStep) {
        FlowOrder flowOrder = repository.findOne(flowOrderId);
        User user = userRepository.findOne(userId);
        if (flowOrder.getCurrentStep() == currentStep) {
            return flowOrder;
        }

        //设置超时，存在一个步骤超时，整个工单则设为超时
        Long countDown = getCountDown(flowOrder);
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        if(cal.getTimeInMillis() > countDown) {
            flowOrder.setIsOverTime((short)1);
        }

        if(flowOrder.getFlowOrderType().getMaxStep() == currentStep) {
            flowOrder.setIsFinish((short)1);
            //工单处理完结时才记录用户超时
            if(flowOrder.getIsOverTime() == (short)1) {
                user.setOverTimeCount(user.getOverTimeCount()!=null?user.getOverTimeCount()+1:1);
                userRepository.save(user);
            }
        }

        FlowOrderLog log = new FlowOrderLog();
        log.setTimeLimit(getTimeLimit(flowOrder));

        flowOrder.setCurrentStep(flowOrder.getCurrentStep() + 1);
        flowOrder.setUser(user);
        flowOrder.setUpdateTime(new Date());
        repository.save(flowOrder);

        log.setTimeFinish(CommonUtils.getNowTimeNormalString());
        log.setContent(logContent);
        log.setFlowOrder(flowOrder);
        log.setHandleUser(user.getRealname());
        flowOrderLogRepository.save(log);

        return flowOrder;
    }
    @Override
    public void saveCancelOrder(Long flowOrderId, Long userId, String cancelReason) {
        saveCancelOrder(flowOrderId, userId, cancelReason, false);
    }

    public Long saveCancelOrder(Long flowOrderId, Long userId, String cancelReason, boolean processFlow) {
        FlowOrder flowOrder;
        if(processFlow) {
            flowOrder = process(flowOrderId, userId, "退号登记", 1);
        } else {
            flowOrder = repository.findOne(flowOrderId);
            flowOrder.setCurrentStep(4);
        }
        repository.save(flowOrder);

        User user = userRepository.findOne(userId);
        Order order = flowOrder.getOrder();
        order.setCancelReason(cancelReason);
        order.setStatus(OrderStatusEnum.CANCELED.getKey() + "");
        order.setUpdateTime(CommonUtils.getNowTimeShortString());
        order.setUpdateUser(user.getRealname());
        orderRepository.save(order);

        user.setCancelOrderCount(user.getCancelOrderCount()!=null?user.getCancelOrderCount()+1:1);
        userRepository.save(user);

        OrderHistory history = new OrderHistory("取消订单", "修改订单状态为已取消(80)", order, user.getRealname(), CommonUtils.getNowTimeShortString());
        orderHistoryRepository.save(history);

        return getCountDown(flowOrder);
    }

    @Override
    public void cancelOrderFromMiddle(Long orderId, Long userId) {
        initFlowOrder(orderId, userId, new Long(FlowOrderTypeEnum.CANCEL_ORDER.getKey()));
    }

    @Override
    public void reSignOrderFromMiddle(Long orderId, Long userId) {
        initFlowOrder(orderId, userId, new Long(FlowOrderTypeEnum.RESIGN_ORDER.getKey()));
    }

    /**
     * 退单，不退号，订单不受影响，退到中台重新指派
     * @param flowOrderId
     * @param userId
     */
    @Override
    public void saveCancelFlowOrder(Long flowOrderId, Long userId) {
        FlowOrder flowOrder = repository.findOne(flowOrderId);
        flowOrder.setIsAssign((short)0);  //订单状态不改变，改派后继续之前的流程
        repository.save(flowOrder);

        User user = userRepository.findOne(userId);
        user.setCancelFlowOrderCount(user.getCancelFlowOrderCount()!=null?user.getCancelFlowOrderCount()+1:1);
        userRepository.save(user);
    }

    @Override
    public List<UserTask> getAllTask(Long hospitalId) {
        List<UserTask> taskList = new ArrayList<UserTask>();
        List<Object[]> taskArrayList;
        if(hospitalId == null || hospitalId == 0) {
            taskArrayList = repository.findAllUnassigned();
        } else {
            taskArrayList = repository.findUnassignedByHospital(hospitalId);
        }
        for (Object[] taskArray : taskArrayList) {
            if (taskArray != null && taskArray.length == 3) {
                UserTask task = new UserTask();
                task.setCount(Long.valueOf(taskArray[0].toString()));
                task.setFlowOrderType(dictService.getFlowOrderType(Long.valueOf(taskArray[1].toString())));
                task.setOrderType(dictService.getOrderType(Long.valueOf(taskArray[2].toString())));
                taskList.add(task);
            }
        }

        return taskList;
    }

    @Override
    public List<FlowOrder> getUserTask(Long userId) {
        return repository.findUnFinishedByUser(userId, (short)0);
    }

    @Override
    public void saveAssignInfo(Long flowOrderId, Long userId) {
        FlowOrder flowOrder = repository.findOne(flowOrderId);
        flowOrder.setIsAssign((short)1);

        User user = userRepository.findOne(userId);
        flowOrder.setUser(user);
        flowOrder.setCurrentStep(0);
        flowOrder.setUpdateTime(new Date());
        flowOrder.setIsFinish((short)0);
        flowOrder.setIsEvaluate((short)0);
        flowOrder.setIsOverTime((short)0);  //如果是改派也将超时标记设置为0
        repository.save(flowOrder);

        user.setFlowOrderCount(user.getFlowOrderCount()!=null?user.getFlowOrderCount()+1:1);
        userRepository.save(user);
    }

    @Override
    public OrderReport getOrderReport(Long flowOrderId) {
        OrderReport report = new OrderReport();
        FlowOrder flowOrder = repository.findOne(flowOrderId);
        Order order = flowOrder.getOrder();

        //执行记录
        OrderExecutionRecord record = orderExecutionRecordRepository.findFirstByOrder(order);
        report.setRecord(record);

        //异常指标
        List<OrderExceptionData> dataList = IteratorUtils.toList(orderExceptionDataRepository.findByOrder(order).iterator());
        report.setExceptionDataList(dataList);

        //诊断结果
        List<OrderDiagnose> diagnoseList = IteratorUtils.toList(orderDiagnoseRepository.findByOrder(order).iterator());
        report.setDiagnoseList(diagnoseList);

        //用药记录
        List<Medicines> medicinesList = IteratorUtils.toList(orderMedicineRepository.findByOrder(order).iterator());
        report.setMedicinesList(medicinesList);

        //附件
        if(order.getOrderType().equals(OrderTypeEnum.DIAGNOSE.getKey()+"")) {
            List<UploadFile> fileList = uploadFileRepository.findAllByRelatedKeyAndUseType(order.getId().toString(), PictureUseTypeEnum.DIAGNOSE.getKey());
            report.setFileList(fileList);
        } else if(order.getOrderType().equals(OrderTypeEnum.PHYSICAL_CHECK.getKey()+"")) {
            List<UploadFile> fileList = uploadFileRepository.findAllByRelatedKeyAndUseType(order.getId().toString(), PictureUseTypeEnum.PHYSICAL_CHECK.getKey());
            report.setFileList(fileList);
        }

        return report;
    }

    private FlowOrder initFlowOrder(Long orderId, Long userId, Long flowOrderTypeId) {
        Order order = orderRepository.findOne(orderId);
        User user = userRepository.findOne(userId);
        //生成工单
        FlowOrder flowOrder = new FlowOrder();
        flowOrder.setIsOverTime((short)0);
        flowOrder.setIsEvaluate((short)0);
        flowOrder.setIsFinish((short)0);
        flowOrder.setUpdateTime(new Date());
        flowOrder.setCurrentStep(0);
        flowOrder.setUser(user);
        flowOrder.setIsAssign((short)1);
        flowOrder.setOrder(order);
        flowOrder.setOrderType(orderTypeRepository.findOne(Long.valueOf(order.getOrderType())));
        flowOrder.setFlowOrderType(flowOrderTypeRepository.findOne(flowOrderTypeId));
        flowOrder.setCreateTime(new Date());

        flowOrder.setScore((short)0);
        flowOrder.setMoney(0D);

        if(flowOrder.getFlowOrderType() != null) {
            if(flowOrder.getFlowOrderType().getDefaultScore() != null) {
                flowOrder.setScore(flowOrder.getFlowOrderType().getDefaultScore().shortValue());
                if(flowOrder.getFlowOrderType().getPrice() != null) {
                    String d = df.format(flowOrder.getFlowOrderType().getPrice()*flowOrder.getFlowOrderType().getDefaultScore()*1.0D/10);
                    flowOrder.setMoney(new Double(d));
                }
            }
        }

        repository.save(flowOrder);
        return flowOrder;
    }
}